# -*- coding: utf-8 -*-
"""
@desc: 公共操作
@author: 然诺
@contact: rannuo1010@gmail.com
@time: 2019/4/10 23:40
@file: PersonalRank.py
"""
import os
import random


def base_contribution_score():
    """
    基本贡献函数
    :return: 分数
    """
    return 1


def read_file(path):
    """
    读取文件数据
    :param file_path: 源文件路径
    :return: 文件操作对象
    """
    # 文件不存在，直接返回
    if not os.path.exists(path):
        print("文件不存在")
        return None
    # 文件存在，打开文件
    fp = open(path, encoding='utf-8')
    return fp


def get_data(rating_file):
    """
    读取用户数据
    :param rating_file:
    :return:
    """
    # 调用自定义函数读取首行除外的文件数据
    fp = read_file(rating_file)
    if fp is None:
        return {}
    # 返回一个数据结构
    data = []
    # 按行遍历文件数据
    for line in fp:
        item = line.strip().split('::')
        # 跳过长度不符合要求的行
        if len(item) < 4:
            continue
        [user_id, item_id, rating, timestamp] = item
        # 跳过评分小于阈值（3）的行
        # if float(rating) < 3.0:
        #     continue
        data.append((int(user_id), int(item_id), float(rating), int(timestamp)))
    fp.close()
    print("读取用户数据完成！")
    return data


def split_u_data(data, M, k, seed):
    """
    划分训练集、测试集
    将用户行为数据集按照均匀分布随机分成M份，挑选一份作为测试集，将剩下的M-1份作为训练集
    :param data:源数据
    :param M:数据集划分份数
    :param k:一个任意的数字，用来随机筛选测试集和训练集
    :param seed:随机数种子，在seed一样的情况下，生成的随机序列是相同
    :return:train-训练集test-测试集
    """
    train = {}
    test = {}
    random.seed(seed)
    for user, item, rating, _ in data:
        # 划分
        if random.randint(0, M) == k:
            test.setdefault(user, {})
            test[user][item] = rating
        else:
            train.setdefault(user, {})
            train[user][item] = rating
    return train, test


def split_data(data, M, k, seed):
    """
    划分训练集、测试集
    将用户行为数据集按照均匀分布随机分成M份，挑选一份作为测试集，将剩下的M-1份作为训练集
    :param data:源数据
    :param M:数据集划分份数
    :param k:一个任意的数字，用来随机筛选测试集和训练集
    :param seed:随机数种子，在seed一样的情况下，生成的随机序列是相同
    :return:train-训练集test-测试集
    """
    train = {}
    test = {}
    train_item_user = {}
    test_item_user = {}
    random.seed(seed)
    for user, item, rating, _ in data:
        # 划分
        if random.randint(0, M) == k:
            test.setdefault(user, {})
            test[user][item] = rating
            test_item_user.setdefault(item, {})
            test_item_user[item][user] = rating
        else:
            train.setdefault(user, {})
            train[user][item] = rating
            train_item_user.setdefault(item, {})
            train_item_user[item][user] = rating
    return train, test, train_item_user, test_item_user


def get_item_info(file_path):
    """
    获取物品信息
    :param file_path: 文件路径
    :return: 物品信息字典
    """
    # 调用自定义函数读取文件数据
    fp = read_file(file_path)
    if fp is None:
        return {}
    # 跳过首行
    next(fp)

    item_info = dict()
    for line in fp:
        # 按逗号切割
        item = line.strip().split(",")
        # 过滤掉长度小于3的行
        if len(item) < 3:
            continue
        elif len(item) == 3:
            item_id, title, genre = item[0], item[1], item[2]
            item_info[item_id] = [title, genre]
        elif len(item) > 3:
            item_id = item[0]
            genre = item[-1]
            title = ",".join(item[1:-1])
            item_info[item_id] = [title, genre]
    fp.close()
    return item_info
